package microcredit.gui.editor.loan;

import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;

import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JTextField;
import javax.swing.SpinnerNumberModel;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import microcredit.gui.base.BaseAction;
import microcredit.gui.selector.AbstractActionPanel;
import microcredit.gui.util.FormatUtilities;
import microcredit.gui.util.MDatePicker;
import microcredit.gui.util.NumericTextField;
import microcredit.gui.util.UIUtil;
import microcredit.model.MemberToLoan;
import microcredit.model.MemberToLoanHistory;
import microcredit.model.domain.LoanExtensionReason;
import net.miginfocom.swing.MigLayout;

import com.jidesoft.swing.JideButton;
import com.jidesoft.swing.TitledSeparator;
import com.lowagie.text.Font;

public class LoanExtensionPanel extends AbstractActionPanel {
	private JLabel extensionStartLabel;
	private MDatePicker extensionStartDatePicker;
	private JLabel numberOfWeeksLabel;
	private JSpinner numberOfWeeksSpinner;
	private JLabel reasonLabel;
	private ExtensionReasonCombobox reasonComboBox;
	
	private final LoanGeneralForm form;
	private JTextField reasonTextField;
	
	private JLabel newExtensionStartValueLabel;
	private JLabel newExtensionWeeksValueLabel;
	private JLabel descriptionLabel;
	
	private boolean editable = true;
	private boolean reasonEditable = true;
	private JLabel customRateLabel;
	private NumericTextField customRateTextField;
	private JLabel customRateValueLabel;
	private JLabel loanLabel;
	private NumericTextField loanTextField;
	private JLabel interestLabel;
	private NumericTextField interestTextField;
	private JLabel loanValueLabel;
	private JLabel interestValueLabel;
	private TitledSeparator titledSeparator;
	
	private final RemoveExtensionAction removeExtensionAction = new RemoveExtensionAction(this);
	private JideButton removeExtensionButton;
	private JLabel extensionLabel;
	
	public LoanExtensionPanel(LoanGeneralForm form) {
		this.form = form;
		initializeActions();
		initialize();
		initListeners();
		UIUtil.setMandatoryFields(this, MemberToLoan.NUMBER_OF_WEEKS,
				MemberToLoan.START_DATE,
				MemberToLoan.EXTENSION_REASON);
	}
	
	private void initializeActions() {
		addAction(removeExtensionAction);
	}
	
	public boolean isEditable() {
		return editable;
	}
	
	public void setEditable(boolean editable) {
		this.editable = editable;
		getLoanTextField().setVisible(editable);
		getInterestTextField().setVisible(editable);
		getExtensionStartDatePicker().setVisible(editable);
		getNumberOfWeeksSpinner().setVisible(editable);
		getCustomRateTextField().setVisible(editable);
		getReasonComboBox().setVisible(editable);
		getReasonTextField().setVisible(editable);
		
		getLoanValueLabel().setVisible(!editable);
		getInterestValueLabel().setVisible(!editable);
		getNewExtensionStartValueLabel().setVisible(!editable);
		getNewExtensionWeeksValueLabel().setVisible(!editable);
		getCustomRateValueLabel().setVisible(!editable);
		
		getReasonLabel().setVisible(editable);
		getDescriptionLabel().setVisible(editable);
	}
	
	public boolean isReasonEditable() {
		return reasonEditable;
	}
	
	public void setReasonEditable(boolean editable) {
		this.reasonEditable = editable;
		getReasonComboBox().setEnabled(editable);
		getReasonTextField().setEditable(editable);
		getReasonTextField().setEnabled(editable);
	}

	private void initListeners() {
		getNumberOfWeeksSpinner().addChangeListener(new ChangeListener() {
			public void stateChanged(ChangeEvent e) {
				form.dataChanged();
			}
		});
		getExtensionStartDatePicker().addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				form.dataChanged();
			}
		});
		 PropertyChangeListener listener = new PropertyChangeListener() {
		     public void propertyChange(PropertyChangeEvent e) {
		         if ("date".equals(e.getPropertyName())) {
		        	 form.dataChanged();
		         }
		     }
		 };
		 getExtensionStartDatePicker().addPropertyChangeListener(listener);
		 DocumentListener documentListener = new DocumentListener() {
			@Override
			public void removeUpdate(DocumentEvent e) {
				form.dataChanged();
			}
			@Override
			public void insertUpdate(DocumentEvent e) {
				form.dataChanged();
			}
			@Override
			public void changedUpdate(DocumentEvent e) {
				form.dataChanged();
			}
		};
		getCustomRateTextField().getDocument().addDocumentListener(documentListener);
		getLoanTextField().getDocument().addDocumentListener(documentListener);
		getInterestTextField().getDocument().addDocumentListener(documentListener);
	}
	
	public void apply(MemberToLoan loan, MemberToLoanHistory history) {
		setEditable(loan.getLastHistory() == history);
		setReasonEditable(true);
		
		Date startDate = history.getStartDate();
		Integer weeks = history.getNewNumberOfWeeks();
		LoanExtensionReason reason = history.getExtensionReason();
		String reasonText = history.getReasonText();
		BigDecimal customRate = history.getRepaymentRate();
		BigDecimal loanAmount = history.getLoanAmount();
		BigDecimal interestPercentage = history.getInterestPercentage();
		
		getExtensionStartDatePicker().setDate(startDate);
		getReasonComboBox().setValue(reason);
		if (weeks != null) {
			getNumberOfWeeksSpinner().setValue(weeks);
		}
		getReasonTextField().setText(reasonText);
		getNewExtensionStartValueLabel().setText(FormatUtilities.formatLongDate(startDate));
		getNewExtensionWeeksValueLabel().setText(weeks != null ? weeks.toString() : "");
		getCustomRateValueLabel().setText(FormatUtilities.formatMoney(customRate));
		getLoanValueLabel().setText(FormatUtilities.formatMoney(loanAmount));
		getInterestValueLabel().setText(FormatUtilities.formatMoney(interestPercentage)+" %");
		
		LoanPanel.updateNumericTextField(getCustomRateTextField(), customRate);
		getNumberOfWeeksSpinner().setEnabled(customRate == null);
		LoanPanel.updateNumericTextField(getLoanTextField(), loanAmount);
		LoanPanel.updateNumericTextField(getInterestTextField(), interestPercentage);
		
		int index = loan.getMemberToLoanHistories().indexOf(history);
		
		extensionLabel.setText("Extension No " + index + " ");
		removeExtensionButton.setVisible(isEditable());
		
		updateState();
	}
	
	public MemberToLoan receive(MemberToLoan loan, MemberToLoanHistory history) {
		if (!isEditable()) {
			return loan;
		}
		
		Date startDate = getExtensionStartDatePicker().getDate();
		Integer weeks = (Integer)getNumberOfWeeksSpinner().getValue();
		LoanExtensionReason reason = getReasonComboBox().getValue();
		String reasonText = getReasonTextField().getText();
		BigDecimal customRate = null;
		try {
			customRate = (BigDecimal)getCustomRateTextField().getNumberValue();
		} catch (ParseException e) {
		}
		BigDecimal loanAmount = null;
		try {
			loanAmount = (BigDecimal)getLoanTextField().getNumberValue();
		} catch (ParseException e) {
		}
		BigDecimal interestPercentage = null;
		try {
			interestPercentage = (BigDecimal)getInterestTextField().getNumberValue();
		} catch (ParseException e) {
		}
		
		history.setLoanAmount(loanAmount);
		history.setExtensionReason(reason);
		history.setNewNumberOfWeeks(weeks);
		history.setReasonText(reasonText);
		history.setStartDate(startDate);
		history.setRepaymentRate(customRate);
		history.setInterestPercentage(interestPercentage);
		
		// will be done in generateLoanEntries
//		if (loan.getLastHistory() == history){
//			loan.setLoanAmount(loanAmount);
//			loan.setInterestPercentage(interestPercentage);
//			loan.setNumberOfWeeks(weeks);
//			loan.setRepaymentRate(customRate);
//		}
		
		return loan;
	}
	
	private void initialize() {
		setLayout(new MigLayout("insets 0, hidemode 3", "[][trailing][][grow,trailing][grow]", "[][][][][][]"));
		add(getTitledSeparator(), "flowx,cell 1 1 4 1,grow");
		add(getLoanLabel(), "cell 1 2,alignx trailing");
		add(getLoanTextField(), "flowx,cell 2 2");
		add(getInterestLabel(), "cell 3 2,alignx trailing");
		add(getInterestTextField(), "flowx,cell 4 2");
		add(getExtensionStartLabel(), "cell 1 3");
		add(getExtensionStartDatePicker(), "flowx,cell 2 3,grow");
		add(getNumberOfWeeksLabel(), "cell 3 3");
		add(getNumberOfWeeksSpinner(), "flowx,cell 4 3");
		add(getReasonLabel(), "cell 1 4,alignx trailing,gapx 10 null");
		add(getReasonComboBox(), "cell 2 4");
		add(getCustomRateLabel(), "cell 3 4,alignx trailing");
		add(getCustomRateTextField(), "flowx,cell 4 4");
		add(getDescriptionLabel(), "cell 1 5,alignx trailing");
		add(getReasonTextField(), "cell 2 5 3 1,growx");
		
		add(getLoanValueLabel(), "cell 2 2");
		add(getNewExtensionStartValueLabel(), "cell 2 3");
		add(getInterestValueLabel(), "cell 4 2");
		add(getNewExtensionWeeksValueLabel(), "cell 4 3 2 1");
		add(getCustomRateValueLabel(), "cell 4 4 2 1");
	}

	private JLabel getExtensionStartLabel() {
		if (extensionStartLabel == null) {
			extensionStartLabel = new JLabel("Start date:");
		}
		return extensionStartLabel;
	}
	private MDatePicker getExtensionStartDatePicker() {
		if (extensionStartDatePicker == null) {
			extensionStartDatePicker = new MDatePicker();
			extensionStartDatePicker.setName(MemberToLoan.START_DATE);
		}
		return extensionStartDatePicker;
	}
	private JLabel getNumberOfWeeksLabel() {
		if (numberOfWeeksLabel == null) {
			numberOfWeeksLabel = new JLabel("No of weeks:");
		}
		return numberOfWeeksLabel;
	}
	private JSpinner getNumberOfWeeksSpinner() {
		if (numberOfWeeksSpinner == null) {
			numberOfWeeksSpinner = new JSpinner();
			numberOfWeeksSpinner.setModel(new SpinnerNumberModel(0, 0, 200, 1));
			numberOfWeeksSpinner.setName(MemberToLoan.NUMBER_OF_WEEKS);
			((JSpinner.NumberEditor)numberOfWeeksSpinner.getEditor()).getTextField().addFocusListener(new FocusListener() {
				@Override
				public void focusLost(FocusEvent e) {
				}
				
				@Override
				public void focusGained(FocusEvent e) {
					int value = (Integer)getNumberOfWeeksSpinner().getValue();
					if (value == 0) {
						((JSpinner.NumberEditor)getNumberOfWeeksSpinner().getEditor()).getTextField().setText("");
					}
				}
			});
		}
		return numberOfWeeksSpinner;
	}
	private JLabel getReasonLabel() {
		if (reasonLabel == null) {
			reasonLabel = new JLabel("Reason:");
		}
		return reasonLabel;
	}
	private ExtensionReasonCombobox getReasonComboBox() {
		if (reasonComboBox == null) {
			reasonComboBox = new ExtensionReasonCombobox();
			reasonComboBox.setName(MemberToLoan.EXTENSION_REASON);
			reasonComboBox.enableAutocompletion();
		}
		return reasonComboBox;
	}
	private JTextField getReasonTextField() {
		if (reasonTextField == null) {
			reasonTextField = new JTextField();
			reasonTextField.setColumns(10);
			reasonTextField.setName(MemberToLoan.EXTENSION_DESCRIPTION);
		}
		return reasonTextField;
	}
	private JLabel getNewExtensionStartValueLabel() {
		if (newExtensionStartValueLabel == null) {
			newExtensionStartValueLabel = new JLabel("23.12.1973");
		}
		return newExtensionStartValueLabel;
	}
	private JLabel getNewExtensionWeeksValueLabel() {
		if (newExtensionWeeksValueLabel == null) {
			newExtensionWeeksValueLabel = new JLabel("13");
		}
		return newExtensionWeeksValueLabel;
	}
	private JLabel getDescriptionLabel() {
		if (descriptionLabel == null) {
			descriptionLabel = new JLabel("Description:");
		}
		return descriptionLabel;
	}

	public void focusDefault() {
		if (isEditable()) {
			getNumberOfWeeksSpinner().requestFocus();
		} else if (isReasonEditable()) {
			getReasonComboBox().requestFocus();
		}
	}
	private JLabel getCustomRateLabel() {
		if (customRateLabel == null) {
			customRateLabel = new JLabel("Custom rate:");
		}
		return customRateLabel;
	}
	private NumericTextField getCustomRateTextField() {
		if (customRateTextField == null) {
			customRateTextField = new NumericTextField();
			customRateTextField.setColumns(5);
		}
		return customRateTextField;
	}
	private JLabel getCustomRateValueLabel() {
		if (customRateValueLabel == null) {
			customRateValueLabel = new JLabel("1000");
		}
		return customRateValueLabel;
	}
	private JLabel getLoanLabel() {
		if (loanLabel == null) {
			loanLabel = new JLabel("Loan:");
		}
		return loanLabel;
	}
	private NumericTextField getLoanTextField() {
		if (loanTextField == null) {
			loanTextField = new NumericTextField();
			loanTextField.setColumns(10);
			loanTextField.setName(MemberToLoan.LOAN_AMOUNT);
		}
		return loanTextField;
	}
	private JLabel getInterestLabel() {
		if (interestLabel == null) {
			interestLabel = new JLabel("Interest:");
		}
		return interestLabel;
	}
	private NumericTextField getInterestTextField() {
		if (interestTextField == null) {
			interestTextField = new NumericTextField();
			interestTextField.setColumns(4);
			interestTextField.setName(MemberToLoan.INTEREST_PERCENTAGE);
		}
		return interestTextField;
	}
	private JLabel getLoanValueLabel() {
		if (loanValueLabel == null) {
			loanValueLabel = new JLabel("100.00");
		}
		return loanValueLabel;
	}
	private JLabel getInterestValueLabel() {
		if (interestValueLabel == null) {
			interestValueLabel = new JLabel("5%");
		}
		return interestValueLabel;
	}
	private TitledSeparator getTitledSeparator() {
		if (titledSeparator == null) {
			titledSeparator = new TitledSeparator();
			JPanel panel = new JPanel();
			panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
			removeExtensionButton = new JideButton();
			removeExtensionButton.setAction(removeExtensionAction);
			extensionLabel = new JLabel("Loan extension");
			extensionLabel.setFont(extensionLabel.getFont().deriveFont(Font.BOLD));
			panel.add(extensionLabel);
			panel.add(removeExtensionButton);
			titledSeparator.setLabelComponent(panel);
		}
		return titledSeparator;
	}
	
	private class RemoveExtensionAction extends BaseAction {
		public RemoveExtensionAction(Component parent) {
			super(parent);
			setName("");
			setIcon("x16/delete2.png");
		}

		@Override
		public void perform(ActionEvent e) throws Throwable {
			form.removeLastExtension();
		}
		
		@Override
		public void updateState() throws Throwable {
		}
	}
	
}

